<template>
	<el-dialog
		v-model="isShowCopper"
		:title="props.title"
		:width="props.width"
		:destroy-on-close="true"
		:close-on-click-modal="false"
		@close="closeCopperDialog"
	>
		<el-row :style="{ height: props.height + 'px' }">
			<el-col :span="props.isPreview ? 12 : 24">
				<VueCropper
					ref="vueCropperRef"
					fill-color="#FFF"
					:img="options.img"
					:fixed-box="props.fixedBox"
					:auto-crop="options.autoCrop"
					:auto-crop-width="options.autoCropWidth"
					:auto-crop-height="options.autoCropHeight"
					@realTime="realTime"
				/>
			</el-col>
			<el-col :span="12" v-if="props.isPreview">
				<div style="font-size: 20px; text-align: center">&nbsp;&nbsp;&nbsp;效果预览</div>
				<div class="avatar-upload-preview">
					<img :src="previews.url" :style="previews.img" />
				</div>
			</el-col>
		</el-row>
		<template #footer>
			<div class="avatar-dialog-footer">
				<div class="avatar-dialog-footer-left">
					<el-upload
						action="#"
						:show-file-list="false"
						:http-request="requestUpload"
						:before-upload="beforeUpload"
					>
						<el-button><HIcon name="ele-UploadFilled" :size="16" />选择图片</el-button>
					</el-upload>
					<div>
						<el-button @click="vueCropperRef.changeScale(1)">
							<HIcon name="ele-ZoomIn" :size="16" />放大
						</el-button>
						<el-button @click="vueCropperRef.changeScale(-1)">
							<HIcon name="ele-ZoomOut" :size="16" />缩小
						</el-button>
						<el-button @click="vueCropperRef.rotateLeft()">
							<HIcon name="ele-RefreshLeft" :size="16" />左旋
						</el-button>
						<el-button @click="vueCropperRef.rotateRight()">
							<HIcon name="ele-RefreshRight" :size="16" />右旋
						</el-button>
					</div>
				</div>
				<div class="avatar-dialog-footer-right">
					<el-button type="default" @click="isShowCopper = false">取 消</el-button>
					<el-button type="primary" @click="getCropData">确 定</el-button>
				</div>
			</div>
		</template>
	</el-dialog>
</template>

<script setup lang="ts" name="imageCropper">
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
import type { UploadRawFile } from "element-plus";
import { VueCropper } from "vue-cropper";
import "vue-cropper/dist/index.css";

const emits = defineEmits(["getCroppedImg"]);

// 定义传值
interface imageCropperProps {
	title?: string; // 弹窗标题
	width?: number; // 弹窗宽度
	height?: number; // 弹窗高度
	cropWith?: number; // 裁剪框宽度
	cropHeight?: number; // 裁剪框高度
	fixedBox?: boolean; // 是否固定裁剪框大小
	isPreview?: boolean; // 是否显示图片编辑预览
}
const props = withDefaults(defineProps<imageCropperProps>(), {
	title: "编辑图片",
	width: 1200,
	height: 500,
	cropWith: 300,
	cropHeight: 300,
	fixedBox: true,
	isPreview: true,
});

// 定义变量内容
const vueCropperRef = ref();
const isShowCopper = ref(false); // 是否显示图片裁剪弹窗
const previews = ref<EmptyObjectType>({}); // 预览图片信息
const options = reactive({
	img: "", // 原图地址
	imgName: "", // 图片名称
	imgType: "", // 图片类型
	autoCrop: true, // 是否默认生成截图框
	autoCropWidth: props.cropWith, // 默认生成截图框宽度
	autoCropHeight: props.cropHeight, // 默认生成截图框高度
});

// 打开图片裁剪弹窗
const openCopperDialog = (imageSrc: string, cropAspect: number[] = []) => {
	options.img = imageSrc || "";
	options.imgName = "";
	options.imgType = "";
	if (cropAspect.length === 2) {
		options.autoCropWidth = cropAspect[0];
		options.autoCropHeight = cropAspect[1];
	} else {
		options.autoCropWidth = props.cropWith;
		options.autoCropHeight = props.cropHeight;
	}
	isShowCopper.value = true;
};
// 关闭图片裁剪弹窗
const closeCopperDialog = () => {
	isShowCopper.value = false;
};
// 图片裁剪实时预览
const realTime = (data: EmptyObjectType) => {
	previews.value = data;
};
// 覆盖默认的上传行为
const requestUpload = () => {};
// 上传前的钩子函数
const beforeUpload = (file: UploadRawFile) => {
	if (file.type.indexOf("image/") == -1) {
		ElMessage.error("文件格式错误，请上传图片文件，如 png、jpg、jpeg 后缀的文件");
	} else {
		const reader = new FileReader();
		reader.readAsDataURL(file);
		reader.onload = () => {
			options.img = reader.result as any;
			options.imgName = file.name;
			options.imgType = file.type;
		};
	}
};
// 获取裁剪后的图片
const getCropData = () => {
	vueCropperRef.value.getCropBlob(async (blob: any) => {
		emits("getCroppedImg", { blob, name: options.imgName, type: options.imgType });
	});
};

defineExpose({ openCopperDialog, closeCopperDialog });
</script>

<style scoped lang="scss">
.avatar-upload-preview {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(50%, -50%);
	width: 300px;
	height: 300px;
	border-radius: 50%;
	box-shadow: 0 0 4px #ccc;
	overflow: hidden;
}
.avatar-dialog-footer {
	display: flex;
	justify-content: space-between;
	align-items: center;
	&-left {
		flex: 1;
		text-align: left;
		display: flex;
		justify-content: space-between;
	}
	&-right {
		flex: 1;
		text-align: right;
	}
}
</style>
